package edu.siu.math.egut.main;

import java.io.IOException;

import edu.siu.math.egut.io.Algorithms;
import edu.siu.math.egut.io.LiE;
import edu.siu.math.egut.io.OutputPref;
import edu.siu.math.egut.util.Polynomial;
import edu.siu.math.egut.util.PolynomialReadException;

/**
 * DCA stands for Double Coset Analysis.
 * 
 * 
 * @author Joseph Hundley
 * 
 */
public class DCA_Weyl {
    private static final OutputPref ERR = OutputPref.ERR;
    private static final OutputPref SHOW = OutputPref.SHOW;
    private static final OutputPref HIDE = OutputPref.HIDE;
    private static LiE lie = new LiE();

    /**
     * @param args
     *            group G parabolic P, parabolic Q, polynomial psi, Weyl element
     *            sigma
     */
    public static void main(final String[] args) {

	if (args.length < 4) {
	    System.out
		    .print("Not enough information.  Need:\n "
			    + "\t* group G\n"
			    + "\t* Parabolic P, such that the Fourier coefficient is taken along the \n\tunipotent radical of P,\n"
			    + "\t* Parabolic Q, such that Eisenstein is induced from Q,\n"
			    + "\t* a polynomial psi factor,\n"
			    + "\t* weyl Element sigma\n"
			    + "Parabolics should be specified by listing the simple roots in the\n"
			    + "unipotent radical.\n"
			    + "Example: E8 [2] [1] u_{11221111}+u_{11122111}+u_{12232210}+u_{11233210} [2,4,5,6,7]\n");
	    System.exit(1);

	}

	Polynomial ell = Polynomial.create(1);
	try {
	    ell = Polynomial.read(args[3]);
	} catch (final PolynomialReadException e1) {
	    System.out.println("Problem reading polynomial.");
	    e1.printStackTrace();
	    System.exit(1);
	}

	try {

	    analyze(args[0], args[1], args[2], ell, args[4]);

	} catch (final IOException e) {
	    System.out.println("Problem starting LiE.");
	    e.printStackTrace();
	    System.exit(1);
	} catch (final Exception e) {
	    System.out
		    .println("Exception encountered.  Possible cause:  problem reading LiE output.");

	    e.printStackTrace();
	}

    }// end main

    /**
     * @param pString
     *            defining the parabolic P
     * @param groupName
     *            name of ambient group G
     * @param qString
     *            defining the parabolic Q
     * @param ell
     *            defining the character \psi
     * @param sigmaString
     *            defining a Weyl word sigma
     * @throws IOException
     *             usually as a result of calling lie.exec
     * @throws Exception
     *             various "read" commands
     */
    public static void analyze(String pString, String groupName,
	    String qString, Polynomial ell, String sigmaString)
	    throws IOException, Exception {
	// set default group
	lie.exec("setdefault " + groupName, ERR);
	lie.exec("p = " + pString, ERR);
	lie.exec("q=" + qString, ERR);
	lie.exec("sigma=" + sigmaString, ERR);

	// get w0.
	lie.exec("w0 = lr_reduce(complement(q),sigma, complement(p))", ERR);
	say("sigma = w0 nu0, w0 reduced by Q on left, P on right.\nw0=");
	lie.exec("w0", SHOW);
	say("w0^{-1}Qw0 \\cap M(P)");
	
	// get p1
	lie.exec("p1=complement(complement(p), levi_para( w0,q,p))", ERR);
	lie.exec("p1", SHOW);
	String nu0String = lie.exec("reduce(inverse(w0)^sigma)",
		HIDE);
	say("nu0 = " + nu0String);

	// define nu0 in the LiE process
	lie.exec("nu0 = " + nu0String, ERR);

	// display goesDown( nu0), and collect it into an int[][]
	say("Positive roots sent down by nu0:");
	String goesDown = lie.exec("goesDown( nu0) ", SHOW);

	// for convenience, define U. We call it u in LiE because 'U' is not
	// allowed by LiE.
	lie.exec("u = unipRad(p)", ERR);

	// compute goesUp( w0^nu0, u), and collect it into an int[][]. do not
	// display: we wish to display more precise information using compare.
	lie.exec("u1 = goesUp( w0^nu0, u)", ERR);
	lie.exec("u2 = goesDown(w0^nu0, u)", ERR);
	int[][] uRoots = Algorithms.readLiEMatrix(lie.exec("u1^u2", HIDE));

	say("Roots in U sent up by w0^nu0-- those sent into the Levi first.");
	// display more precise information using compare. first what is mapped
	// up and into the levi, L of Q
	lie.exec("compare( w0^nu0, intersection( u, preimage( w0^nu0, levi("
		+ qString + "))))", SHOW);
	// and then what is mapped into the unipotent radical V.
	lie.exec("compare( w0^nu0, intersection( u, preimage( w0^nu0, unipRad("
		+ qString + "))))", SHOW);

	if (!goesDown.contains("null")) {
	    int[][] deltaRoots = Algorithms.readLiEMatrix(goesDown);

	    ell = edu.siu.math.egut.util.Algorithms.action(deltaRoots, "d",
		    ell, uRoots, "u");
	}// end if( !goesDown.contains("null"))

	System.out.println(ell);

    }

    /**
     * Just to avoid typing System.out.println over and over...
     * 
     * @param string
     *            String
     */
    public static void say(final String string) {
	System.out.println(string);
    }

}// end class
